package com.minidb.sql_compiler;

import com.minidb.utils.Condition;
import com.minidb.utils.Helpers;
import com.minidb.utils.StatementType;

import java.util.HashSet;
import java.util.List;

public class SemanticAnalyzer {
    private final Catalog catalog;

    public SemanticAnalyzer(Catalog catalog) { this.catalog = catalog; }

    private IllegalArgumentException error(SQLStatement s, String msg) {
        if (s.originToken != null) {
            return new IllegalArgumentException("语义错误 @(" +
                    s.originToken.line + "," + s.originToken.col + "): " + msg);
        } else {
            return new IllegalArgumentException("语义错误: " + msg);
        }
    }

    public void analyze(SQLStatement s) throws IllegalArgumentException {
        s.originToken = null; // 用于错误报告
        
        if (s.type == StatementType.CREATE_TABLE) {
            // 修复：统一表名大小写处理，确保一致性
            String normalizedTableName = s.tableName.toUpperCase();
            if (catalog.tableExists(normalizedTableName)) {
                throw error(s, "表已存在 " + s.tableName);
            }
            // 检查列名重复
            HashSet<String> colSet = new HashSet<>();
            for (String col : s.columns) {
                String normalizedCol = col.toUpperCase();
                if (!colSet.add(normalizedCol)) {
                    throw error(s, "重复的列名 " + col);
                }
            }
        } else if (s.type == StatementType.INSERT) {
            // 检查表存在性 - 统一大小写处理
            String normalizedTableName = s.tableName.toUpperCase();
            if (!catalog.tableExists(normalizedTableName)) {
                throw error(s, "表不存在 " + s.tableName);
            }
            
            List<String> tableCols = catalog.getColumns(s.tableName);
            List<String> targetCols = s.columns.isEmpty() ? tableCols : s.columns;
            
            // 检查值数量匹配
            if (s.values.size() != targetCols.size()) {
                throw error(s, "值个数与列数不匹配，期望 " + targetCols.size() + "，得到 " + s.values.size());
            }
            
            // 检查列存在性和类型匹配
            for (int i = 0; i < targetCols.size(); i++) {
                String col = targetCols.get(i);
                String val = s.values.get(i);
                
                if (!tableCols.contains(col)) {
                    throw error(s, "列不存在 " + col);
                }
                
                // 跳过NULL值检查
                if ("NULL".equals(val)) continue;
                
                boolean isInt = catalog.getColumnType(s.tableName, col).startsWith("INT");
                if (isInt && !Helpers.isNumeric(val))
                    throw error(s, "列 "+col+" 需要数字，得到 "+val);
                if (!isInt && Helpers.isNumeric(val))
                    throw error(s, "列 "+col+" 需要字符串，请加引号");
            }
        }
        
        // SELECT和DELETE的WHERE子句检查
        if (s.type == StatementType.SELECT || s.type == StatementType.DELETE) {
            // 检查表存在性
            if (!catalog.tableExists(s.tableName)) {
                throw error(s, "表不存在 " + s.tableName);
            }
            
            // 检查SELECT的列存在性
            if (s.type == StatementType.SELECT && s.columns != null && !s.columns.isEmpty()) {
                List<String> tableCols = catalog.getColumns(s.tableName);
                for (String col : s.columns) {
                    if (!"*".equals(col) && !tableCols.contains(col)) {
                        throw error(s, "列不存在 " + col);
                    }
                }
            }
            
            // 检查WHERE子句中的列存在性和类型匹配
            if (s.condition != null) {
                validateCondition(s, s.condition);
            }
        }
    }

    // 新增方法：验证WHERE条件
    private void validateCondition(SQLStatement s, Condition condition) {
        List<String> tableCols = catalog.getColumns(s.tableName);
        
        // 检查列是否存在
        if (!tableCols.contains(condition.columnName)) {
            throw error(s, "WHERE子句中列不存在: " + condition.columnName);
        }
        
        // 检查类型匹配
        String columnType = catalog.getColumnType(s.tableName, condition.columnName);
        boolean isIntColumn = columnType.toUpperCase().contains("INT");
        boolean isNumericValue = Helpers.isNumeric(condition.value);
        
        if (isIntColumn && !isNumericValue) {
            throw error(s, "列 " + condition.columnName + " 是数值类型，但比较值不是数字: " + condition.value);
        }
        
        if (!isIntColumn && isNumericValue && !condition.value.startsWith("'") && !condition.value.startsWith("\"")) {
            throw error(s, "列 " + condition.columnName + " 是文本类型，数值需要加引号: " + condition.value);
        }
    }
}
